import cgi
import os
import base64
import hashlib
import urllib
import json
import oauth
import logging

from datetime import datetime
from datetime import timedelta
from Crypto.PublicKey import RSA
from Crypto.Util import number
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import memcache

class Ranking(db.Model):
  person = db.StringProperty()
  avgeInteligence = db.FloatProperty()
  avgeHumor = db.FloatProperty()
  avgeKiss = db.FloatProperty()
  avgeCatch = db.FloatProperty()
  avgeFaith = db.FloatProperty()
  avgeBeauty = db.FloatProperty()
  avgeBody = db.FloatProperty()
  totalReviews = db.IntegerProperty()

class Review(db.Model):
  author = db.StringProperty()
  authorOrkutId = db.StringProperty()
  owner = db.StringProperty()
  ownerOrkutId = db.StringProperty()
  inteligence = db.IntegerProperty()
  humor = db.IntegerProperty()
  kiss = db.IntegerProperty()
  cat = db.IntegerProperty()
  faith = db.IntegerProperty()
  beauty = db.IntegerProperty()
  body = db.IntegerProperty()
  comment = db.StringProperty(multiline=True)
  date = db.DateTimeProperty(auto_now_add=True)

# complains about a review
class Complaint(db.Model):
  author = db.StringProperty()
  requester = db.StringProperty()
  reasons = db.StringProperty(multiline=True)
  date = db.DateTimeProperty(auto_now_add=True)

#  the profile visits 
class VisitLog(db.Model):
  visitor = db.StringProperty()
  visitorOrkutId = db.StringProperty()
  visitorName = db.StringProperty()
  owner = db.StringProperty()
  ownerOrkutId = db.StringProperty()
  date = db.DateTimeProperty(auto_now_add=True)

# user preferecences
# must be auto-gerenerate when needed
class Preferences(db.Model):
  owner = db.StringProperty()
  anonymous = db.BooleanProperty(default=False)
  rankeable = db.BooleanProperty(default=True)
  receiveFromW = db.BooleanProperty(default=True)
  receiveFromM = db.BooleanProperty(default=True)

# Bases for keys in Memcache
KEY_BASE_FETCH = "FETCH_"  
KEY_BASE_FETCH_VISITLOG = "VISITLOG_" #still not used
KEY_BASE_FETCH_NUMVISITLOG = "NUMVISITLOG_"
KET_BASE_FETCH_AVGRATINGS = "FETCH_AVGRATINGS_"
KET_BASE_FETCH_RANKING = "RANKING_"

public_key_str = """0x\
00b1e057678343866db89d7dec2518\
99261bf2f5e0d95f5d868f81d600c9\
a101c9e6da20606290228308551ed3\
acf9921421dcd01ef1de35dd3275cd\
4983c7be0be325ce8dfc3af6860f7a\
b0bf32742cd9fb2fcd1cd1756bbc40\
0b743f73acefb45d26694caf4f26b9\
765b9f65665245524de957e8c547c3\
58781fdfb68ec056d1"""

# Ratings (aka ranking) related functinos
def get_avg_rating( owner ):
  response = memcache.get(KET_BASE_FETCH_AVGRATINGS+owner)
  if response is not None:
    return response
  else:
    query = db.GqlQuery("SELECT * FROM Ranking WHERE person = :person ", person = owner)
    ratings = query.get()
    if ratings is None:
      return None
    else:
      response = ratings
      memcache.add(KET_BASE_FETCH_AVGRATINGS+owner, response)
  return response

def isValidSignature(self):
  # Construct a RSA.pubkey object
  exponent = 65537
  public_key_long = long(public_key_str, 16)
  public_key = RSA.construct((public_key_long, exponent))
  
  # Rebuild the message hash locally
  oauth_request = oauth.OAuthRequest(http_method=self.request.method, 
                                   http_url=self.request.url, 
                                   parameters=self.request.params.mixed())
  message = '&'.join((oauth.escape(oauth_request.get_normalized_http_method()),
                    oauth.escape(oauth_request.get_normalized_http_url()),
                    oauth.escape(oauth_request.get_normalized_parameters()),))
  local_hash = hashlib.sha1(message).digest()

  # Apply the public key to the signature from the remote host
  sig = base64.decodestring(urllib.unquote(self.request.params.mixed()["oauth_signature"]))
  remote_hash = public_key.encrypt(sig, '')[0][-20:]

  # Verify that the locally-built value matches the value from the remote server.
  if local_hash==remote_hash:
    return True
  else:
    return False
  
# Make a new complaint about a review
class Complain(webapp.RequestHandler):

  def post(self):
    if not isValidSignature(self):
      self.response.out.write(json.write({}))
      return
    query = db.GqlQuery("SELECT * FROM Complaint WHERE author = :author "
	                      "AND requester = :requester ", author = self.request.get('author'),
						  requester = self.request.get('opensocial_viewer_id'))
    result = query.fetch(1)
    db.delete(result)

    complain = Complaint()
    complain.author = self.request.get('author')
    complain.requester = self.request.get('opensocial_viewer_id')
    complain.reasons = self.request.get('reasons')
    complain.put()
    self.response.out.write('{"Error" : "200", "Result" : "OK"}')

# Get the current user's ratings for canvas.
class RatingsRequestHandler(webapp.RequestHandler):
  def get(self):
    ratings = get_avg_rating(self.request.get('owner'))
    if ratings is None:
      response = '{"Error" : "200", "Result" : "OK", "Inteligence" : "0", "Humor" : "0", "Kiss" : "0", "Catch" : "0", "Faith" : "0", "Beauty" : "0", "Body" : "0"}'
    else:
      response = '{"Error" : "200", "Result" : "OK", "Inteligence" : "%f", "Humor" : "%f", "Kiss" : "%f", "Catch" : "%f", "Faith" : "%f", "Beauty" : "%f", "Body" : "%f"}' %(ratings.avgeInteligence, ratings.avgeHumor, ratings.avgeKiss, ratings.avgeCatch, ratings.avgeFaith, ratings.avgeBeauty, ratings.avgeBody)
    self.response.out.write(response)
    
# Get the owner's ratings for profile view.
class ProfileRatingsRequestHandler(webapp.RequestHandler):
  def get(self):
    ratings = get_avg_rating(self.request.get('opensocial_owner_id'))
    if ratings is None:
      response = '{"Error" : "200", "Result" : "OK", "Inteligence" : "0", "Humor" : "0", "Kiss" : "0", "Catch" : "0", "Faith" : "0", "Beauty" : "0", "Body" : "0"}'
    else:
      response = '{"Error" : "200", "Result" : "OK", "Inteligence" : "%f", "Humor" : "%f", "Kiss" : "%f", "Catch" : "%f", "Faith" : "%f", "Beauty" : "%f", "Body" : "%f"}' %(ratings.avgeInteligence, ratings.avgeHumor, ratings.avgeKiss, ratings.avgeCatch, ratings.avgeFaith, ratings.avgeBeauty, ratings.avgeBody)
    self.response.out.write(response)  

# Get a defined number o reviews from the owner.
class ReviewsRequestHandler(webapp.RequestHandler):
  def get(self):
    if not isValidSignature(self):
      self.response.out.write(json.write({}))
      return

    number = int(self.request.get('number',1))
    owner = self.request.get('owner')
    # cacheable
    if number == 0 or number == 1: 
      response = memcache.get(KEY_BASE_FETCH + "_" + str(number) + "_" +owner)
      if response is None:
        query = db.GqlQuery("SELECT * FROM Review WHERE owner = :own ORDER BY date DESC", own = owner)
        if number > 0:
          reviews = query.fetch(number)
        else:
          reviews = query.fetch(1000)

        i = 0
        response = '{"Error" : "200", "Result" : "OK", "Reviews" : ['
        for review in reviews:
          response += '{"Author" : "%s", "Owner" : "%s", "Comment" : "%s"},' %(review.author, review.owner, review.comment)
          i = i + 1
        if i > 0:
          response = response[0:len(response)-1]+']}'
        else:
          response = response +']}'
        memcache.add(KEY_BASE_FETCH + "_" + str(number) + "_" + owner, response)
      self.response.out.write(response)
    else:
      query = db.GqlQuery("SELECT * FROM Review WHERE owner = :own ORDER BY date DESC", own = owner)
      reviews = query.fetch(number)
      response = '{"Error" : "200", "Result" : "OK", "Reviews" : ['
      for review in reviews:
        response += '{"Author" : "%s", "Owner" : "%s", "Comment" : "%s"},' %(review.author, review.owner, review.comment)
        i = i + 1
      if i > 0:
        response = response[0:len(response)-1]+']}'
      else:
        response = response +']}'
      self.response.out.write(response)

# Make a new review
class Deploy(webapp.RequestHandler):
  def post(self):
    if not isValidSignature(self):
      self.response.out.write(json.write({}))
      return
    query = db.GqlQuery("SELECT * FROM Review WHERE author = :author "
	                      "AND owner = :owner ", author = self.request.get('author'),
						  owner = self.request.get('owner'))
    result = query.get()
	
	# Updating the Ranking for the owner of the review
    ranking = get_avg_rating(self.request.get('owner'))

    if ranking is None:
      ranking = Ranking()
      ranking.person = self.request.get('owner')
      ranking.avgeInteligence = float(self.request.get('inteligence'))
      ranking.avgeHumor = float(self.request.get('humor'))
      ranking.avgeKiss = float(self.request.get('kiss'))
      ranking.avgeCatch = float(self.request.get('cat'))
      ranking.avgeFaith = float(self.request.get('faith'))
      ranking.avgeBeauty = float(self.request.get('beauty'))
      ranking.avgeBody = float(self.request.get('body'))
      ranking.totalReviews = 1

    else:
      if result is not None:
        if (ranking.totalReviews - 1) != 0:
          ranking.avgeInteligence = ((ranking.avgeInteligence * ranking.totalReviews) - result.inteligence) / (ranking.totalReviews - 1)
          ranking.avgeHumor = ((ranking.avgeHumor * ranking.totalReviews) - result.humor) / (ranking.totalReviews - 1)
          ranking.avgeKiss = ((ranking.avgeKiss * ranking.totalReviews) - result.kiss) / (ranking.totalReviews - 1)
          ranking.avgeCatch = ((ranking.avgeCatch * ranking.totalReviews) - result.cat) / (ranking.totalReviews - 1)
          ranking.avgeFaith = ((ranking.avgeFaith * ranking.totalReviews) - result.faith) / (ranking.totalReviews - 1)
          ranking.avgeBeauty = ((ranking.avgeBeauty * ranking.totalReviews) - result.beauty) / (ranking.totalReviews - 1)
          ranking.avgeBody = ((ranking.avgeBody * ranking.totalReviews) - result.body) / (ranking.totalReviews - 1)
        ranking.totalReviews = ranking.totalReviews - 1
        db.delete(result)

      ranking.avgeInteligence = ((ranking.avgeInteligence * ranking.totalReviews) + int(self.request.get('inteligence'))) / (ranking.totalReviews + 1)
      ranking.avgeHumor = ((ranking.avgeHumor * ranking.totalReviews) + int(self.request.get('humor'))) / (ranking.totalReviews + 1)
      ranking.avgeKiss = ((ranking.avgeKiss * ranking.totalReviews) + int(self.request.get('kiss'))) / (ranking.totalReviews + 1)
      ranking.avgeCatch = ((ranking.avgeCatch * ranking.totalReviews) + int(self.request.get('cat'))) / (ranking.totalReviews + 1)
      ranking.avgeFaith = ((ranking.avgeFaith * ranking.totalReviews) + int(self.request.get('faith'))) / (ranking.totalReviews + 1)
      ranking.avgeBeauty = ((ranking.avgeBeauty * ranking.totalReviews) + int(self.request.get('beauty'))) / (ranking.totalReviews + 1)
      ranking.avgeBody = ((ranking.avgeBody * ranking.totalReviews) + int(self.request.get('body'))) / (ranking.totalReviews + 1)
      ranking.totalReviews = ranking.totalReviews + 1    

    review = Review()
    review.author = self.request.get('author')
    review.authorOrkutId = self.request.get('authorOrkutId')
    review.owner = self.request.get('owner')
    review.ownerOrkutId = self.request.get('ownerOrkutId')
    review.inteligence = int(self.request.get('inteligence'))
    review.humor = int(self.request.get('humor'))
    review.kiss = int(self.request.get('kiss'))
    review.cat = int(self.request.get('cat'))
    review.faith = int(self.request.get('faith'))
    review.beauty = int(self.request.get('beauty'))
    review.body = int(self.request.get('body'))
    review.comment = self.request.get('comment')
    if int(self.request.get('inteligence')) < 0 or int(self.request.get('inteligence')) > 5 or int(self.request.get('humor')) < 0 or int(self.request.get('humor')) > 5 or int(self.request.get('kiss')) < 0 or int(self.request.get('kiss')) > 5 or int(self.request.get('cat')) < 0 or int(self.request.get('cat')) > 5 or int(self.request.get('faith')) < 0 or int(self.request.get('faith')) >5 or int(self.request.get('beauty')) < 0 or int(self.request.get('beauty')) > 5 or int(self.request.get('body')) < 0 or int(self.request.get('body')) > 5:
      self.response.out.write('{"Error" : "500", "Result" : "ERROR"}')
    else:
      memcache.delete(KEY_BASE_FETCH + "_0_" + self.request.get('owner'))
      memcache.delete(KEY_BASE_FETCH + "_1_" + self.request.get('owner'))
      memcache.delete(KET_BASE_FETCH_AVGRATINGS + self.request.get('owner'))
      review.put()
      ranking.put()
      self.response.out.write('{"Error" : "200", "Result" : "OK"}')

# Delete a review
class Delete(webapp.RequestHandler):
  def get(self):
    if not isValidSignature(self):
      self.response.out.write(json.write({}))
      return
    query = db.GqlQuery("SELECT * FROM Review WHERE author = :author "
	                      "AND owner = :owner ", author = self.request.get('author'),
						  owner = self.request.get('owner'))
    result = query.get()
	
	# Updating the Ranking for the owner of the review
    ranking = get_avg_rating(self.request.get('owner'))
    if ranking is not None:
      if (ranking.totalReviews - 1) != 0:
        ranking.avgeInteligence = ((ranking.avgeInteligence * ranking.totalReviews) - result.inteligence) / (ranking.totalReviews - 1)
        ranking.avgeHumor = ((ranking.avgeHumor * ranking.totalReviews) - result.humor) / (ranking.totalReviews - 1)
        ranking.avgeKiss = ((ranking.avgeKiss * ranking.totalReviews) - result.kiss) / (ranking.totalReviews - 1)
        ranking.avgeCatch = ((ranking.avgeCatch * ranking.totalReviews) - result.cat) / (ranking.totalReviews - 1)
        ranking.avgeFaith = ((ranking.avgeFaith * ranking.totalReviews) - result.faith) / (ranking.totalReviews - 1)
        ranking.avgeBeauty = ((ranking.avgeBeauty * ranking.totalReviews) - result.beauty) / (ranking.totalReviews - 1)
        ranking.avgeBody = ((ranking.avgeBody * ranking.totalReviews) - result.body) / (ranking.totalReviews - 1)
        ranking.totalReviews = ranking.totalReviews - 1
        ranking.put()
      else:
        db.delete(ranking)
    db.delete(result)
    memcache.delete(KEY_BASE_FETCH + "_0_" + self.request.get('owner'))
    memcache.delete(KEY_BASE_FETCH + "_1_" + self.request.get('owner'))
    memcache.delete(KET_BASE_FETCH_AVGRATINGS + self.request.get('owner'))
    self.response.out.write('{"Error" : "200", "Result" : "OK"}')

# Class for getting ranking
class RankingRequestHandler(webapp.RequestHandler):

  def post(self):
    owner = self.request.get('owner')
    friendList = json.read(self.request.get('friends'))
    currentId = self.request.get('currentid')
    
    # checking cache
    incache = memcache.get(KET_BASE_FETCH_RANKING+owner+"_"+currentId)
    if incache is not None:
      self.response.out.write(json.write(incache))
      logging.info("Ranking cache hit: %s %s" % (owner, currentId) )
      return
    
    #sub caching
    ratingList = memcache.get(KET_BASE_FETCH_RANKING+owner)
    if ratingList is not None:
      logging.info("Ranking sub-cache hit: %s" % (owner) )
    if ratingList is None:
      #find adjust factor based on number of reviews
      def findAdjustFactor( numberReviews ):
        if numberReviews == 0: # error?
          return 0.0
        elif numberReviews == 1:
          return 1.0
        elif numberReviews > 1 and numberReviews <= 3:
          return 1.0 + 0.1*numberReviews
        elif numberReviews > 3 and numberReviews <= 10:
          return 1.3 + 0.01*numberReviews
        else:
          return 1.4 + 0.001*numberReviews
       
      #creates a ranking instance with 0 values and visit
      def newRanking( person ):
        ranking = Ranking()
        ranking.person = person
        ranking.avgeInteligence = float(0)
        ranking.avgeHumor = float(0)
        ranking.avgeKiss = float(0)
        ranking.avgeCatch = float(0)
        ranking.avgeFaith = float(0)
        ranking.avgeBeauty = float(0)
        ranking.avgeBody = float(0)
        ranking.totalReviews = 0
        return ranking
    
    
      ratingList = []
      # geting all ratings and putting them into tuples
      avgRating = get_avg_rating(owner)
      numVisit = get_num_visits(owner)
      if avgRating is None:
        if numVisit > 0:
          avgRating = newRanking(owner)
        
      if avgRating is not None:
        adjustFactor = findAdjustFactor(avgRating.totalReviews)
        ratingList.append( (avgRating.person, avgRating.avgeInteligence*adjustFactor,  avgRating.avgeHumor*adjustFactor, avgRating.avgeKiss*adjustFactor, avgRating.avgeCatch*adjustFactor, avgRating.avgeFaith*adjustFactor, avgRating.avgeBeauty*adjustFactor, avgRating.avgeBody*adjustFactor, numVisit, avgRating.totalReviews) ) 

    
      for friend in friendList:
        avgRating = get_avg_rating(friend)
        numVisit = get_num_visits(friend)
        if avgRating is None:
          if numVisit > 0:
            avgRating = newRanking(friend)

        if avgRating is not None:
          adjustFactor = findAdjustFactor(avgRating.totalReviews)
          ratingList.append( (avgRating.person, avgRating.avgeInteligence*adjustFactor,  avgRating.avgeHumor*adjustFactor, avgRating.avgeKiss*adjustFactor, avgRating.avgeCatch*adjustFactor, avgRating.avgeFaith*adjustFactor, avgRating.avgeBeauty*adjustFactor, avgRating.avgeBody*adjustFactor, numVisit, avgRating.totalReviews) ) 
      
      memcache.add(KET_BASE_FETCH_RANKING+owner, ratingList, 1800)
    # sorting function, with a specific index
    def SortOnItem(mylist, index):
      templist = [ (line[index], line) for line in mylist ]
      templist.sort()
      templist.reverse()
      return [ val for (key,val) in templist]

    def findItem(myList, id):
      i = 1
      for person in myList:
        if (person[0] == id):
          return i
        i = i+1
      return 0

    answers = dict()
    top5 = dict()
    positions = dict()
    
    #  sorting with each index and putting all in the dict
    ratingList = SortOnItem(ratingList, 1)
    positions["inteligence"] = findItem(ratingList,currentId)
    top5["inteligence"] = [ line[0] for line in ratingList[0:5] ]
    
    ratingList = SortOnItem(ratingList, 2)
    positions["humor"] = findItem(ratingList,currentId)
    top5["humor"] = [ line[0] for line in ratingList[0:5] ]

    ratingList = SortOnItem(ratingList, 3)
    positions["kiss"] = findItem(ratingList,currentId)
    top5["kiss"] = [ line[0] for line in ratingList[0:5] ]

    ratingList = SortOnItem(ratingList, 4)
    positions["catch"] = findItem(ratingList,currentId)
    top5["catch"] = [ line[0] for line in ratingList[0:5] ]    

    ratingList = SortOnItem(ratingList, 5)
    positions["faith"] = findItem(ratingList,currentId)
    top5["faith"] = [ line[0] for line in ratingList[0:5] ] 
    
    ratingList = SortOnItem(ratingList, 6)
    positions["beauty"] = findItem(ratingList,currentId)
    top5["beauty"] = [ line[0] for line in ratingList[0:5] ]
    
    ratingList = SortOnItem(ratingList, 7)
    positions["body"] = findItem(ratingList,currentId)
    top5["body"] = [ line[0] for line in ratingList[0:5] ]

    ratingList = SortOnItem(ratingList, 8)
    positions["popularity"] = findItem(ratingList,currentId)
    top5["popularity"] = [ line[0] for line in ratingList[0:5] ]
    
    answers["pos"] = positions
    answers["top5"] = top5
    self.response.out.write(json.write(answers))
    memcache.add(KET_BASE_FETCH_RANKING+owner+"_"+currentId, answers, 3600)

# Class for logging a visit
class LogVisit(webapp.RequestHandler):
  def post(self):
    visitLog = VisitLog()
    visitLog.visitor = self.request.get('opensocial_viewer_id')
    visitLog.visitorOrkutId = self.request.get('visitorOrkutId')
    visitLog.visitorName = self.request.get('visitorName')
    visitLog.owner = self.request.get('opensocial_owner_id')
    visitLog.ownerOrkutId = self.request.get('ownerOrkutId')

    memcache.delete(KEY_BASE_FETCH_VISITLOG + self.request.get('opensocial_owner_id'))
    memcache.delete(KEY_BASE_FETCH_NUMVISITLOG + self.request.get('opensocial_owner_id'))
    visitLog.put()
    self.response.out.write('{"Error" : "200", "Result" : "OK"}')
    
# Returns the profile visits list for a certain user.
class VisitsRequestHandler(webapp.RequestHandler):
  def get(self):
    owner = self.request.get('owner')
    response = memcache.get(KEY_BASE_FETCH_VISITLOG + owner)
    if response is None:
      query = db.GqlQuery("SELECT * FROM VisitLog WHERE owner = :own ORDER BY date DESC", own = owner)
      visits = query.fetch(1000)
      if len(visits) > 0:
        currentTimeZone = timedelta(hours=-3)
      
        response = '{"Error" : "200", "Result" : "OK", "Visits" : ['
        for visit in visits:
          if owner == "16148452910119311902" or owner == "14526248552994967325":
            response += '{"OrkutId" : "%s", "Name" : "%s", "Date" : "%s"},' %(visit.visitorOrkutId, visit.visitorName, (visit.date + currentTimeZone).strftime("%H:%M %d/%m/%y "))
          else:
            response += '{"Date" : "%s"},' %((visit.date + currentTimeZone).strftime("%H:%M %d/%m/%y "))
        response = response[0:len(response)-1]+']}'
      else:
        response = '{"Error" : "200", "Result" : "OK", "Visits" : []}'
      memcache.add(KEY_BASE_FETCH_VISITLOG + owner, response)
    self.response.out.write(response)

#  Aux function which returns the total number of visits received, using memcache
def get_num_visits( owner ):
  response = memcache.get(KEY_BASE_FETCH_NUMVISITLOG+owner)
  if response is not None:
    return response
  else:
    sevendaysago = datetime.now() - timedelta(days=7)
    query = db.GqlQuery("SELECT * FROM VisitLog WHERE owner = :own AND date > :sevenAgo ORDER BY date DESC", own = owner, sevenAgo = sevendaysago)
   
    response = query.count()
    memcache.add(KEY_BASE_FETCH_NUMVISITLOG+owner, response,86400) # caching for one day!
    delete_old_visits(owner)
  return response
def delete_old_visits( owner ):
  sevendaysago = datetime.now() - timedelta(days=7)
  query = db.GqlQuery("SELECT * FROM VisitLog WHERE owner = :owner AND date < :sevenAgo ORDER BY date DESC", owner = owner, sevenAgo = sevendaysago)
  results = query.fetch(1000)
  db.delete(results)

# debugging only! !  using functions above
class VisitsNumberHandler(webapp.RequestHandler):
  def get(self):
    count = get_num_visits(self.request.get('owner'))
    self.response.out.write('{"Error" : "200", "Result" : "OK", "NumVisits" : "%d"}' % count)
    # removing old visists
    delete_old_visits(self.request.get('owner'))

# Class for fixing/updating ids
class Update(webapp.RequestHandler):
  def post(self):
    reviews = db.GqlQuery("SELECT * FROM Review WHERE owner = :owner "
							"ORDER BY date DESC", owner = self.request.get('owner'))
                            
    for review in reviews:
      review.ownerOrkutId = self.request.get('ownerOrkutId')
      review.put()
        
    reviews = db.GqlQuery("SELECT * FROM Review WHERE author = :owner "
							"ORDER BY date DESC", owner = self.request.get('owner'))
                            
    for review in reviews:
      review.authorOrkutId = self.request.get('ownerOrkutId')
      review.put()

# Updating the Ranking, needs to be done only once. DONE ALREADY, DO NOT EXECUTE IT AGAIN.
class UpdateRanking(webapp.RequestHandler):
  def get(self):
    reviews = db.GqlQuery("SELECT * FROM Review")
    self.response.out.write("<html><body>")
    for review in reviews:
      query = db.GqlQuery("SELECT * FROM Ranking WHERE person = :owner ", owner = review.owner)
      ranking = query.get()
      if ranking is None:
        ranking = Ranking()
        ranking.person = review.owner
        ranking.avgeInteligence = float(review.inteligence)
        ranking.avgeHumor = float(review.humor)
        ranking.avgeKiss = float(review.kiss)
        ranking.avgeCatch = float(review.cat)
        ranking.avgeFaith = float(review.faith)
        ranking.avgeBeauty = float(review.beauty)
        ranking.avgeBody = float(review.body)
        ranking.totalReviews = 1
        ranking.put()
      else:
        ranking.avgeInteligence = ((ranking.avgeInteligence * ranking.totalReviews) + review.inteligence) / (ranking.totalReviews + 1)
        ranking.avgeHumor = ((ranking.avgeHumor * ranking.totalReviews) + review.humor) / (ranking.totalReviews + 1)
        ranking.avgeKiss = ((ranking.avgeKiss * ranking.totalReviews) + review.kiss) / (ranking.totalReviews + 1)
        ranking.avgeCatch = ((ranking.avgeCatch * ranking.totalReviews) + review.cat) / (ranking.totalReviews + 1)
        ranking.avgeFaith = ((ranking.avgeFaith * ranking.totalReviews) + review.faith) / (ranking.totalReviews + 1)
        ranking.avgeBeauty = ((ranking.avgeBeauty * ranking.totalReviews) + review.beauty) / (ranking.totalReviews + 1)
        ranking.avgeBody = ((ranking.avgeBody * ranking.totalReviews) + review.body) / (ranking.totalReviews + 1)
        ranking.totalReviews = ranking.totalReviews + 1
        ranking.put()
    self.response.out.write("Updated the Ranking.")
    self.response.out.write("</body></html>")

# Clears the Ranking information, useful for development purposes. DO NOT EXECUTE IT.
class ClearRanking(webapp.RequestHandler):
  def get(self):
    query = db.GqlQuery("SELECT * FROM Ranking")
    result = query.fetch(1000)
    db.delete(result)
    self.response.out.write("<html><body>")
    self.response.out.write("Cleared the Ranking.")
    self.response.out.write("</body></html>")

# memcache debug class
class CacheStats(webapp.RequestHandler):
  def get(self):
    logging.debug("Cache stats begin")
    if self.request.get('clear') != '':
      memcache.flush_all()
      logging.info("Cache cleared/flushed")
    
    stats = memcache.get_stats()
    if stats is not None:
      logging.debug("stats is not None")
      self.response.out.write("<html><body>")
      self.response.out.write("<b>Cache Hits:%s</b><br>" % stats['hits'])
      self.response.out.write("<b>Cache Misses:%s</b><br><br>" % stats['misses'])
      self.response.out.write("<b>Cache Items:%s</b><br>" % stats['items'])
      self.response.out.write("<b>Cache Bytes:%s</b><br>" % stats['bytes'])
      self.response.out.write("<b>Cache oldest_item_age:%s</b><br>" % stats['oldest_item_age'])
      self.response.out.write("<b>Cache byte_hits:%s</b><br>" % stats['byte_hits'])
      self.response.out.write("</body> </html>")

# Shows the environment variables.
class Version(webapp.RequestHandler):
  def get(self):
    self.response.out.write("<html><body>")
    for name in os.environ.keys():
      self.response.out.write("%s = %s<br />\n" % (name, os.environ[name]))
    self.response.out.write("</body></html>")
  
# Used for development purposes only.
class Sandbox(webapp.RequestHandler):
  def get(self):
    reviews = db.GqlQuery("SELECT * FROM Review WHERE owner = :owner "
							"ORDER BY date DESC", owner = '16148452910119311902')
    response = ''  
    response += '{"Error" : "200", "Result" : "OK", "Reviews" : ['
    for review in reviews:
      response += '{"Author" : "%s", "Owner" : "%s", "Inteligence" : "%d", "Humor" : "%d", "Kiss" : "%d", "Cat" : "%d", "Faith" : "%d", "Beauty" : "%d", "Body" : "%d", "Comment" : "%s"},' %(review.author, review.owner, review.inteligence, review.humor, review.kiss, review.cat, review.faith, review.beauty, review.body, review.comment)
    responseFinal = response[0:len(response)-1]+']}'
    self.response.out.write("<html><body>")
    self.response.out.write(responseFinal)
    self.response.out.write("</body></html>")

application = webapp.WSGIApplication(
                                     [('/deploy', Deploy),
                                      ('/ratings', RatingsRequestHandler),
                                      ('/profratings', ProfileRatingsRequestHandler),
                                      ('/reviews', ReviewsRequestHandler),
                                      ('/visits', VisitsRequestHandler),
                                      ('/numvisits', VisitsNumberHandler),
                                      ('/delete', Delete),
                                      ('/complain', Complain),
                                      ('/Update', Update),
                                      ('/CacheStats', CacheStats),
                                      ('/LogVisit', LogVisit),
                                      ('/ranking', RankingRequestHandler),
                                      ('/Sandbox', Sandbox),
                                      ('/Version', Version)],
                                     debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()